﻿using System;

namespace Pfz.Factoring
{
	/// <summary>
	/// Class used to set results in an unbound way.
	/// Initially used by Searchers and Editors.
	/// </summary>
	public sealed class ResultSetter:
		IDisposable
	{
		[ThreadStatic]
		private static Action<object> _resultSetter;

		private Action<object> _oldSetter;
		/// <summary>
		/// Creates a new ResultSetter instance, telling the action to do when a new result is set.
		/// </summary>
		public ResultSetter(Action<object> newResultSetter)
		{
			if (newResultSetter == null)
				throw new ArgumentNullException("newResultSetter");

			_oldSetter = _resultSetter;
			_resultSetter = newResultSetter;
		}

		/// <summary>
		/// Restores the old result-setter.
		/// </summary>
		public void Dispose()
		{
			_resultSetter = _oldSetter;
		}

		/// <summary>
		/// Tries to set a result using the last setter registered.
		/// Returns false if none is registered.
		/// </summary>
		public static bool TrySetResult(object result)
		{
			var handler = _resultSetter;
			if (handler == null)
				return false;

			handler(result);
			return true;
		}

		/// <summary>
		/// Sets the Result using the last registered setter.
		/// Throws an InvalidOperationException if there is no setter registered.
		/// </summary>
		public static void SetResult(object result)
		{
			var handler = _resultSetter;
			if (handler == null)
				throw new InvalidOperationException("There is no active ResultSetter.");

			handler(result);
		}
	}
}
